<template>
    <!-- 选项栏 -->
    <div class="flex flex-wrap gap-2 ml-2 mb-2">
        <!-- 总数量 -->
        <el-text tag="b">总数：{{ data.length }}</el-text>
        <!-- 分隔符 -->
        <el-divider direction="vertical" style="height: 32px" />
        <!-- 行高 -->
        <el-tooltip effect="dark" content="调整行高" placement="bottom">
            <el-input-number style="width: 120px" v-model="rowHeight" :min="80" :max="120" :step="5" step-strictly />
        </el-tooltip>

        <!-- 搜索框 -->
        <el-input
            v-model="searchSupplierValue"
            style="width: 180px"
            placeholder="请输入供应商关键字查询"
            clearable
            @clear="inputClearEvent"
            @keydown.enter="searchSupplierEvent"
        />
        <el-button :icon="Search" @click="searchSupplierEvent">搜索</el-button>

        <!-- 选项 -->
        <el-button-group>
            <el-button :icon="Refresh" type="primary" @click="updateForm()">刷新</el-button>
            <el-button v-if="available" :icon="Hide" type="primary" @click="showNoAvailableSupplierList">未激活列表</el-button>
            <el-button v-if="!available" :icon="View" type="primary" @click="showAvailableSupplierList">激活列表</el-button>
            <el-button v-if="checkPermi(['supplier:create'])" :icon="Plus" type="primary" @click="createSupplierEvent">添加</el-button>
            <el-popconfirm v-if="checkPermi(['supplier:delete'])" title="删除后将无法找回，谨慎操作！" @confirm="deleteDictionaryEvent">
                <template #reference>
                    <el-button :icon="Delete" type="primary">删除</el-button>
                </template>
            </el-popconfirm>
            <el-button :icon="Histogram" type="primary" @click="reorderSupplierPriorityEvent">供应商编号排序</el-button>
        </el-button-group>

        <!-- 多种方式导入 -->
        <el-dropdown v-if="checkPermi(['supplier:import/export'])">
            <span class="el-dropdown-link">
                <el-button type="primary" :icon="ArrowDown">导入</el-button>
            </span>
            <template #dropdown>
                <el-dropdown-menu>
                    <!-- json文件导入 -->
                    <el-dropdown-item>
                        <el-upload
                            ref="upload"
                            :auto-upload="false"
                            :show-file-list="false"
                            @change="handleFileChange"
                            :limit="1"
                            :on-exceed="handleExceed"
                            accept=".json"
                        >
                            <el-button type="primary" :icon="TableImport">.json文件导入</el-button>
                        </el-upload>
                    </el-dropdown-item>
                    <!-- xlsx模板导入 -->
                    <el-dropdown-item>
                        <el-upload
                            ref="upload"
                            :auto-upload="false"
                            :show-file-list="false"
                            @change="handleFileChange"
                            :limit="1"
                            :on-exceed="handleExceed"
                            accept=".xlsx"
                        >
                            <el-button type="primary" :icon="Template">.xlsx模板导入</el-button>
                        </el-upload>
                    </el-dropdown-item>
                    <!-- 下载xlsx模板 -->
                    <el-dropdown-item>
                        <el-button type="primary" :icon="Download" @click="downloadSupplierTemplateEvent">下载.xlsx模板</el-button>
                    </el-dropdown-item>
                    <!-- 拉取服务器数据 -->
                    <el-dropdown-item>
                        <el-button type="primary" :icon="ArrowRouting24Regular" @click="pullSupplierListEvent">从服务器拉取</el-button>
                    </el-dropdown-item>
                </el-dropdown-menu>
            </template>
        </el-dropdown>

        <!-- 多种方式导出 -->
        <el-dropdown v-if="checkPermi(['supplier:import/export'])">
            <span class="el-dropdown-link">
                <el-button type="primary" :icon="ArrowDown">导出</el-button>
            </span>
            <template #dropdown>
                <el-dropdown-menu>
                    <!-- json格式文件导出 -->
                    <el-dropdown-item>
                        <el-button type="primary" :icon="TableExport" @click="exportSupplierJsonEvent">.json格式导出</el-button>
                    </el-dropdown-item>
                    <!-- xlsx格式文件导出 -->
                    <el-dropdown-item>
                        <el-button type="primary" :icon="Template" @click="exportSupplierXlsxEvent">.xlsx格式导出</el-button>
                    </el-dropdown-item>
                    <!-- 推送到服务器 -->
                    <el-dropdown-item>
                        <el-button type="primary" :icon="GitPullRequest" @click="pushSupplierListEvent">推送至服务器</el-button>
                    </el-dropdown-item>
                </el-dropdown-menu>
            </template>
        </el-dropdown>
    </div>

    <!-- 表格展示 -->
    <div style="height: calc(100vh - 140px); width: 100%; overflow: auto">
        <el-auto-resizer>
            <template #default="{ height, width }">
                <FTableV2
                    v-model="selected"
                    :data="data"
                    :width="width"
                    :height="height"
                    :row-height="rowHeight"
                    :other-column="otherColumn"
                    :disable="disable"
                    @update-data="updateData"
                ></FTableV2>
            </template>
        </el-auto-resizer>
    </div>

    <!-- 创建供应商弹窗 -->
    <el-dialog v-model="createVisible" :show-close="false" width="50%" :close-on-click-modal="false">
        <!-- 自定义标题 -->
        <template #header="{ close, titleId, titleClass }">
            <!-- 自定义标题内容 -->
            <div class="dialog-header">
                <!-- 标题文字 -->
                <h4 :id="titleId" :class="titleClass">增加供应商<el-text type="warning" size="large"> --- ESC关闭</el-text></h4>
                <!-- 关闭按钮 -->
                <el-button type="danger" @click="close">
                    <el-icon class="el-icon--left">
                        <CircleCloseFilled />
                    </el-icon>
                    关闭
                </el-button>
            </div>
        </template>
        <!-- 自定义内容 -->
        <el-form ref="formRef" :model="form" status-icon :rules="rules" label-width="auto">
            <el-form-item label="排序：" prop="priority">
                <el-input-number v-model="form.priority" :min="1" :max="10000" />
            </el-form-item>
            <el-form-item label="供应商名称：" prop="supplierName">
                <el-input v-model="form.supplierName" type="text" autocomplete="off" />
            </el-form-item>
            <el-form-item label="供应商简称：" prop="supplierAbbreviation">
                <el-input v-model="form.supplierAbbreviation" type="text" />
            </el-form-item>
            <el-form-item label="纳税人识别号：" prop="supplierTaxpayerIdentificationNumber">
                <el-input v-model="form.supplierTaxpayerIdentificationNumber" type="text" />
            </el-form-item>
            <el-form-item label="联系人：" prop="supplierContact">
                <el-input v-model="form.supplierContact" type="text" />
            </el-form-item>
            <el-form-item label="联系方式：" prop="supplierPhone">
                <el-input v-model="form.supplierPhone" type="text" />
            </el-form-item>
            <el-form-item label="地址：" prop="supplierAddress">
                <el-input v-model="form.supplierAddress" type="text" />
            </el-form-item>
            <el-form-item label="开票资料：" prop="supplierInvoiceInfo">
                <el-input v-model="form.supplierInvoiceInfo" type="text" />
            </el-form-item>
            <el-form-item class="justify-end">
                <el-button @click="resetForm(formRef)">重置</el-button>
                <el-button type="primary" @click="submitForm(formRef)"> 提交 </el-button>
            </el-form-item>
        </el-form>
    </el-dialog>
</template>

<script setup lang="tsx">
import { Refresh, Search, Plus, Delete, CircleCloseFilled, Download, ArrowDown, Hide, View, Histogram } from '@element-plus/icons-vue';
import { TableImport, TableExport, Template, GitPullRequest } from '@vicons/tabler';
import { ArrowRouting24Regular } from '@vicons/fluent';
import { Column, ElInput, FormInstance, FormRules, genFileId } from 'element-plus';
import { UploadFile, UploadFiles, UploadInstance, UploadProps, UploadRawFile } from 'element-plus';
import {
    getSupplierList,
    createSupplier,
    importSupplier,
    updateSupplier,
    deleteSupplier,
    reorderSupplierPriority,
    pushSupplierList,
    pullSupplierList,
} from '@api/supplier';
import { downloadSupplierTemplate } from '@api/download';
import { useUserStore } from '@/store/modules/user';
import { checkPermi, checkRole } from '@/utils/permission';
import dayjs from 'dayjs';
import { read, utils, writeFile } from 'xlsx';
import { FunctionalComponent } from 'vue';
import { useDictionaryStore } from '@/store/modules/dictionary';

onMounted(() => {
    generateDisableColumn();
    updateForm();
});

/* ******************************通用属性/方法****************************** */
// 字典数据
const useDictionary = useDictionaryStore();
// 表格数据激活的状态
const available = ref(true);
// 勾选的表格数据
const selected = reactive<string[]>([]);
// 更新表格的方法
const updateForm = (message: string = '查询激活供应商成功') => {
    // 清空表格数据
    dataCache.splice(0);
    selected.splice(0);
    data.length = 0;
    // 获取供应商列表
    getSupplierList(available.value).then((res) => {
        // @ts-ignore
        res.data.forEach((item: any, index: number) => {
            item.checked = false;
            item.order = index + 1;
            item.editing = false;
            data.push(item);
            dataCache.push(item);
        });
        ElMessage({
            message,
            type: 'success',
            grouping: true,
        });
    });
};
// 更新数据的方法
const updateData = (id: string, field: Column['dataKey'], value: string | boolean | number | any[]) => {
    if (checkPermi(['supplier:update'])) {
        updateSupplier({ id, field, value }).then(() => {
            updateForm('更新供应商信息成功');
        });
    }
};

/* ******************************组件el-table-v2 表格属性****************************** */
// 表格数据
const data = reactive<AjaxResponse['supplierList']>([]);
// 缓存数据
let dataCache: AjaxResponse['supplierList'] = [];

// input函数式组件
type InputCessProps = {
    value: string;
    // 在 Input 值改变时触发
    onInput: (value: string) => void;
    // 当选择器的输入框获得焦点时触发
    onFocus: () => void;
    // 当选择器的输入框失去焦点时触发
    onBlur: () => void;
};
const InputCell: FunctionalComponent<InputCessProps> = ({ value, onFocus, onBlur, onInput }) => {
    return <ElInput modelValue={value} type={'number'} onFocus={onFocus} onBlur={onBlur} onInput={onInput} />;
};
// 输入框的原始值
let inputOriginValue = 0;
// 禁用列
const disable = reactive<string[]>([]);
// 表格独有的column
const otherColumn = reactive<{ [key: string]: Column<any> }>({
    priority: {
        key: 'priority',
        dataKey: 'priority',
        width: 80,
        align: 'center',
        title: '编号',
        cellRenderer: ({ rowData, column }) => {
            // 输入框编辑模式
            const onEnterEditMode = () => {
                rowData.editing = true;
                inputOriginValue = rowData[column.dataKey!];
            };

            // 输入框内容改变时触发
            const onInput = (value: string) => {
                rowData[column.dataKey!] = value;
            };

            // 输入框退出编辑模式 -- 更新到服务器
            const onExitEditMode = () => {
                // 输入框退出编辑模式
                rowData.editing = false;
                // 对比新旧值
                if (Number(rowData[column.dataKey!]) !== Number(inputOriginValue)) {
                    // 更新到服务器
                    updateData(rowData._id, column.dataKey!, rowData[column.dataKey!]);
                }
            };

            // 判断是否为文本类型
            return rowData.editing ? (
                <InputCell value={rowData[column.dataKey!]} onFocus={onEnterEditMode} onBlur={onExitEditMode} onInput={onInput} />
            ) : (
                <div class={'table-v2-inline-editing-trigger'} onClick={onEnterEditMode}>
                    {rowData[column.dataKey!]}
                </div>
            );
        },
    },
});
// 生成禁用列 -- 根据字典提供的权限加工otherColumn对象生成禁用列表
const generateDisableColumn = () => {
    // 遍历所有字段
    for (const key in otherColumn) {
        if (Object.prototype.hasOwnProperty.call(otherColumn, key)) {
            // 获取key在字典中的数据
            const { definition, roles } = useDictionary.getDictionaryUseField(key);
            // 判断是否为空
            if (definition == '') {
                disable.push(key);
                break;
            }
            // 判断当前用户是否有权限查看该字段
            if (!checkRole(roles)) {
                disable.push(key);
            }
        }
    }
};
// 行高
const rowHeight = ref(80);

/* ******************************搜索供应商属性/方法****************************** */
// 搜索值
const searchSupplierValue = ref('');
// 搜索事件
const searchSupplierEvent = () => {
    if (searchSupplierValue.value == '') {
        // 原始数据
        data.length = 0;
        dataCache.forEach((item) => {
            data.push(item);
        });
    } else {
        // 筛选数据
        data.length = 0;
        dataCache.forEach((item) => {
            if (item.supplierAbbreviation.includes(searchSupplierValue.value) || item.supplierName.includes(searchSupplierValue.value)) {
                data.push(item);
            }
        });
    }
};
// 输入框清空事件
const inputClearEvent = () => {
    // 原始数据
    data.length = 0;
    dataCache.forEach((item) => {
        data.push(item);
    });
};

/* ******************************创建供应商属性/方法****************************** */
// 创建供应商弹窗
const createVisible = ref(false);
// 创建供应商弹窗事件
const createSupplierEvent = () => {
    createVisible.value = true;
};
// 表单ref
const formRef = ref();
// 创建供应商的表单数据
const form = reactive({
    priority: 0,
    supplierName: '',
    supplierAbbreviation: '',
    supplierTaxpayerIdentificationNumber: '',
    supplierInvoiceInfo: '',
    supplierContact: '',
    supplierPhone: '',
    supplierAddress: '',
    creator: useUserStore().username,
    creatorId: useUserStore().id,
});
// 自定义表单验证规则
const rules = reactive<FormRules<typeof form>>({
    priority: [{ required: true }],
    supplierName: [{ required: true, message: '供应商名称不能为空', trigger: 'blur' }],
    supplierAbbreviation: [{ required: true, message: '供应商简称不能为空', trigger: 'blur' }],
    supplierTaxpayerIdentificationNumber: [{ required: true, message: '纳税人识别号不能为空', trigger: 'blur' }],
});
// 表单重置事件
const resetForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    formEl.resetFields();
};
// 表单提交事件
const submitForm = (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    formEl.validate((valid) => {
        if (valid) {
            createSupplier(form).then((res) => {
                updateForm(res.message);
                createVisible.value = false;
            });
        } else {
            ElMessage.error('请填写必填项');
        }
    });
};

/* ******************************展示未激活供应商属性/方法****************************** */
const showNoAvailableSupplierList = () => {
    available.value = false;
    updateForm('查询未激活供应商成功');
};

/* ******************************展示激活供应商属性/方法****************************** */
const showAvailableSupplierList = () => {
    available.value = true;
    updateForm();
};

/* ******************************删除供应商属性/方法****************************** */
const deleteDictionaryEvent = () => {
    if (selected.length == 0) {
        ElMessage({
            message: '请先勾选要删除的数据！',
            type: 'warning',
            grouping: true,
        });
    } else {
        deleteSupplier(selected).then(() => {
            updateForm('删除成功');
        });
    }
};

/* ******************************排序所有供应商顺序属性/方法****************************** */
const reorderSupplierPriorityEvent = () => {
    reorderSupplierPriority().then(() => {
        updateForm('排序成功');
    });
};

/* ******************************导入供应商属性/方法****************************** */
// 上传实例
const upload = ref<UploadInstance>();
// 上传文件excel/json
const handleFileChange = (uploadFile: UploadFile, _uploadFiles: UploadFiles) => {
    if (uploadFile.name.includes('.xlsx')) {
        // 读取excel文件
        const reader = new FileReader();
        reader.readAsArrayBuffer(uploadFile.raw as File);

        // 当读取完成时
        reader.onload = () => {
            // 需要上传的数据
            const _data: any[] = [];

            /* 解析工作簿 */
            const workbook = read(reader.result);

            /* 获取第一个工作表 */
            const worksheet = workbook.Sheets[workbook.SheetNames[0]];
            const raw_data = utils.sheet_to_json(worksheet, { header: 1 });

            /* 解析数据 */
            try {
                for (let index = 1; index < raw_data.length; index++) {
                    const raw = raw_data[index] as any;
                    // 去空
                    if (raw.length !== 0) {
                        // 检测priority
                        if (raw[0] === '' || raw[0] === null || raw[0] === undefined) {
                            throw new Error('优先级必须填写！');
                        }
                        _data.push({
                            priority: raw[0] || '',
                            supplierName: raw[1] || '',
                            supplierAbbreviation: raw[2] || '',
                            supplierTaxpayerIdentificationNumber: raw[3] || '',
                            supplierContact: raw[4] || '',
                            supplierPhone: raw[5] || '',
                            supplierAddress: raw[6] || '',
                            supplierInvoiceInfo: raw[7] || '',
                        });
                    }
                }
            } catch (error) {
                ElMessage.error('优先级必须填写！');
            }

            // 导入数据库
            if (_data.length > 0) importSupplierEvent(_data);
        };
    } else {
        // 读取json文件
        const reader = new FileReader();
        // @ts-ignore
        reader.readAsText(uploadFile.raw);
        // 当读取完成时
        reader.onload = () => {
            // @ts-ignore
            const data = JSON.parse(reader.result);
            // 检查数据的合法性并加工数据
            if (checkData(data)) {
                importSupplierEvent(data);
            }
        };
    }
};
// 上传文件超出限制覆盖前一个文件
const handleExceed: UploadProps['onExceed'] = (files) => {
    upload.value!.clearFiles();
    const file = files[0] as UploadRawFile;
    file.uid = genFileId();
    upload.value!.handleStart(file);
};
// 检查数据的合法性
const checkData = (data: any): Boolean => {
    // 检测数据类型
    if (typeof data !== 'object') {
        ElMessage.error('导入的数据无法识别');
        return false;
    }

    // 检测数据长度
    if (data.length === 0) {
        ElMessage.error('数据为空无法导入');
        return false;
    }

    // 检测每个数据
    for (let index = 0; index < data.length; index++) {
        const element = data[index];
        let count = 0;
        // 检测每个数据字段
        for (const key in element) {
            if (Object.prototype.hasOwnProperty.call(element, key)) {
                if (
                    key == 'priority' ||
                    key == 'supplierName' ||
                    key == 'supplierAbbreviation' ||
                    key == 'supplierTaxpayerIdentificationNumber' ||
                    key == 'supplierInvoiceInfo' ||
                    key == 'supplierContact' ||
                    key == 'supplierPhone' ||
                    key == 'supplierAddress'
                ) {
                    count++;
                } else {
                    ElMessage.error('数据格式不正确');
                    return false;
                }
            }
        }
        // 检测数据字段数量
        if (count !== 8) {
            ElMessage.error('数据格式数量不正确');
            return false;
        }
    }

    return true;
};
// 文件导入供应商事件
const importSupplierEvent = (data) => {
    const _data = data.map((item) => {
        return {
            ...item,
            creator: useUserStore().username,
            creatorId: useUserStore().id,
        };
    });
    importSupplier(_data).then(() => {
        updateForm('导入成功');
    });
};
// 从服务器拉取供应商列表事件
const pullSupplierListEvent = () => {
    ElMessageBox.prompt('请输入xlsx的密码', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputPattern: /^[A-Za-z0-9]{4,40}$/,
        inputErrorMessage: '四位以上的字母或数字',
    })
        .then(({ value }) => {
            pullSupplierList(value).then((res) => {
                updateForm(res.message);
            });
        })
        .catch(() => {
            ElMessage({
                type: 'info',
                message: '取消拉取',
            });
        });
};

/* ******************************导出供应商属性/方法****************************** */
// 导出json格式供应商列表事件
const exportSupplierJsonEvent = () => {
    if (data.length == 0) {
        ElMessage({
            message: '暂无数据可导出',
            type: 'warning',
            grouping: true,
        });
    } else {
        // 加工导出的数据
        const _data = data.map((item) => {
            return {
                priority: item.priority || '',
                supplierName: item.supplierName || '',
                supplierAbbreviation: item.supplierAbbreviation || '',
                supplierTaxpayerIdentificationNumber: item.supplierTaxpayerIdentificationNumber || '',
                supplierContact: item.supplierContact || '',
                supplierPhone: item.supplierPhone || '',
                supplierAddress: item.supplierAddress || '',
                supplierInvoiceInfo: item.supplierInvoiceInfo || '',
            };
        });
        // 创建一个a标签
        let a: HTMLAnchorElement | null = document.createElement('a');
        // json化导出数据并把地址挂载到a标签上
        a.href = URL.createObjectURL(new Blob([JSON.stringify(_data)]));
        // 设置下载文件名
        a.download = dayjs().format('YYYY-MM-DD_HH-mm-ss@') + 'supplier.json';
        // 模拟下载
        a.click();
        // 释放内存
        a = null;
    }
};
// 导出xlsx格式供应商列表事件
const exportSupplierXlsxEvent = () => {
    if (data.length == 0) {
        ElMessage({
            message: '暂无数据可导出',
            type: 'warning',
            grouping: true,
        });
    } else {
        // 加工导出的数据
        const _data = data.map((item) => {
            return {
                priority: item.priority,
                supplierName: item.supplierName,
                supplierAbbreviation: item.supplierAbbreviation,
                supplierTaxpayerIdentificationNumber: item.supplierTaxpayerIdentificationNumber,
                supplierContact: item.supplierContact,
                supplierPhone: item.supplierPhone,
                supplierAddress: item.supplierAddress,
                supplierInvoiceInfo: item.supplierInvoiceInfo,
            };
        });

        // 生成工作簿和工作表
        const worksheet = utils.json_to_sheet(_data);
        const workbook = utils.book_new();
        utils.book_append_sheet(workbook, worksheet, '供应商列表');

        // 创建标头
        utils.sheet_add_aoa(
            worksheet,
            [['编号', '供应商名称', '简称', '纳税人识别号', '供应商联系人', '供应商联系方式', '供应商公司地址', '开票信息']],
            {
                origin: 'A1',
            }
        );

        // 计算列宽
        worksheet['!cols'] = [{ wch: 5 }, { wch: 25 }, { wch: 15 }, { wch: 30 }, { wch: 15 }, { wch: 20 }, { wch: 40 }, { wch: 40 }];

        writeFile(workbook, `${dayjs().format('YYYY-MM-DD_HH-mm-ss@')}供应商表.xlsx`, { compression: true });
    }
};
// 推送至服务器保存
const pushSupplierListEvent = () => {
    if (data.length == 0) {
        ElMessage({
            message: '暂无数据可导出',
            type: 'warning',
            grouping: true,
        });
    } else {
        ElMessageBox.prompt('请输入xlsx的密码', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            inputPattern: /^[A-Za-z0-9]{4,40}$/,
            inputErrorMessage: '四位以上的字母或数字',
        })
            .then(({ value }) => {
                pushSupplierList(data, value).then(() => {
                    updateForm('推送成功');
                });
            })
            .catch(() => {
                ElMessage({
                    type: 'info',
                    message: '取消推送',
                });
            });
    }
};

/* ******************************下载供应商模板的属性/方法****************************** */
// 下载供应商导入模板的事件
const downloadSupplierTemplateEvent = () => {
    downloadSupplierTemplate().then((res: any) => {
        // 下载数据地址挂载到a标签上
        let a: HTMLAnchorElement | null = document.createElement('a');
        // 创建一个URL表示Blob对象
        a.href = URL.createObjectURL(res);
        // 设置下载文件名
        a.download = '导入供应商列表模板.xlsx';
        // 模拟下载
        a.click();
        // 释放内存
        a = null;
    });
};
</script>

<style></style>
